//// Copyright 2000-2024 JetBrains s.r.o. and contributors. Use of this source code is governed by the Apache 2.0 license.
//package com.linqingying.gitcode.notification
//
//import com.intellij.dvcs.push.VcsPushOptionValue
//import com.intellij.openapi.actionSystem.AnAction
//import com.intellij.openapi.components.service
//import com.intellij.openapi.components.serviceAsync
//import com.intellij.openapi.diagnostic.logger
//import com.intellij.openapi.project.Project
//import git4idea.account.AccountUtil
//import git4idea.account.RepoAndAccount
//import git4idea.branch.GitBranchUtil
//import git4idea.push.GitPushNotificationCustomizer
//import git4idea.push.GitPushRepoResult
//import git4idea.push.isSuccessful
//import git4idea.remote.hosting.knownRepositories
//import git4idea.repo.GitRepository
//import kotlinx.coroutines.CancellationException
//import com.linqingying.gitcode.api.GCGQLRequests
//import com.linqingying.gitcode.api.GCRepositoryCoordinates
//import com.linqingying.gitcode.api.GitCodeApiRequestExecutor
//import com.linqingying.gitcode.api.data.pullrequest.GCPullRequest
//import com.linqingying.gitcode.api.executeSuspend
//import com.linqingying.gitcode.authentication.accounts.GCAccountManager
//import com.linqingying.gitcode.authentication.accounts.GitCodeAccount
//import com.linqingying.gitcode.authentication.accounts.GitCodeProjectDefaultAccountHolder
//import com.linqingying.gitcode.pullrequest.GCRepositoryConnectionManager
//import com.linqingying.gitcode.pullrequest.action.GCPRCreatePullRequestNotificationAction
//import com.linqingying.gitcode.pullrequest.config.GitCodePullRequestsProjectUISettings
//import com.linqingying.gitcode.util.GCGitRepositoryMapping
//import com.linqingying.gitcode.util.GCHostedRepositoriesManager
//
//private val LOG = logger<GCPushNotificationCustomizer>()
//
//internal class GCPushNotificationCustomizer(private val project: Project) : GitPushNotificationCustomizer {
//  private val settings: GitCodePullRequestsProjectUISettings = GitCodePullRequestsProjectUISettings.getInstance(project)
//  private val projectsManager: GCHostedRepositoriesManager = project.service<GCHostedRepositoriesManager>()
//  private val defaultAccountHolder: GitCodeProjectDefaultAccountHolder = project.service<GitCodeProjectDefaultAccountHolder>()
//  private val accountManager: GCAccountManager = service<GCAccountManager>()
//
//  override suspend fun getActions(
//    repository: GitRepository,
//    pushResult: GitPushRepoResult,
//    customParams: Map<String, VcsPushOptionValue>
//  ): List<AnAction> {
//    if (!pushResult.isSuccessful) return emptyList()
//    val (projectMapping, account) = findRepoAndAccount(repository, pushResult) ?: return emptyList()
//    try {
//      val exists = doesReviewExist(pushResult, projectMapping, account)
//      if (exists) return emptyList()
//    }
//    catch (ce: CancellationException) {
//      throw ce
//    }
//    catch (e: Exception) {
//      LOG.warn("Failed to lookup an existing pull request for $pushResult", e)
//      return emptyList()
//    }
//
//    val connection = project.serviceAsync<GCRepositoryConnectionManager>().connectionState.value
//    if (connection?.account != account || connection.repo != projectMapping) return emptyList()
//
//    return listOf(GCPRCreatePullRequestNotificationAction(project, projectMapping, account))
//  }
//
//  private fun findRepoAndAccount(targetRepository: GitRepository, pushResult: GitPushRepoResult): RepoAndAccount<GCGitRepositoryMapping, GitCodeAccount>? {
//    val (url, account) = settings.selectedUrlAndAccount ?: return null
//    val projectMapping = projectsManager.knownRepositories.find { mapping: GCGitRepositoryMapping ->
//      mapping.remote.url == url
//    } ?: return null
//
//    AccountUtil.selectPersistedRepoAndAccount(targetRepository, pushResult, projectMapping to account)?.let {
//      return it
//    }
//    AccountUtil.selectSingleAccount(projectsManager, accountManager, targetRepository, pushResult, defaultAccountHolder.account)?.let {
//      return it
//    }
//
//    return null
//  }
//
//  private suspend fun doesReviewExist(pushResult: GitPushRepoResult, projectMapping: GCGitRepositoryMapping, account: GitCodeAccount): Boolean {
//    val token = accountManager.findCredentials(account) ?: return false
//    val executor = GitCodeApiRequestExecutor.Factory.getInstance().create(account.server, token)
//    val prBranch = getReviewBranch(executor, pushResult, projectMapping, account) ?: return false
//    val pullRequest = getPullRequest(executor, projectMapping, prBranch)
//
//    return pullRequest != null
//  }
//
//  private suspend fun getReviewBranch(
//    executor: GitCodeApiRequestExecutor,
//    pushResult: GitPushRepoResult,
//    projectMapping: GCGitRepositoryMapping,
//    account: GitCodeAccount
//  ): String? {
//    val repositoryInfoRequest = GCGQLRequests.Repo.find(GCRepositoryCoordinates(account.server, projectMapping.repository.repositoryPath))
//    val repositoryInfo = executor.executeSuspend(repositoryInfoRequest) ?: return null
//    val defaultBranch = repositoryInfo.defaultBranch
//    val targetBranch = GitBranchUtil.stripRefsPrefix(pushResult.targetBranch)
//    if (defaultBranch != null && targetBranch.endsWith(defaultBranch)) return null
//
//    return targetBranch.removePrefix("${projectMapping.gitRemote.name}/")
//  }
//
//  private suspend fun getPullRequest(
//    executor: GitCodeApiRequestExecutor,
//    projectMapping: GCGitRepositoryMapping,
//    prBranch: String
//  ): GCPullRequest? {
//    val findPullRequestByBranchesRequest = GCGQLRequests.PullRequest.findByBranches(
//      repository = projectMapping.repository,
//      baseBranch = null,
//      headBranch = prBranch
//    )
//    val targetProjectPath = projectMapping.repository.repositoryPath.toString()
//    return executor.executeSuspend(findPullRequestByBranchesRequest).nodes.find {
//      it.baseRepository?.nameWithOwner == targetProjectPath &&
//      it.headRepository?.nameWithOwner == targetProjectPath
//    }
//  }
//}
